package top.go2do.common.utils;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;

/**
 * @author xingyuji
 * @date 2025/3/20 11:11
 * @description
 */
public class CryptUtils {
    // 迭代次数
    private static final int ITERATIONS = 10;
    // 密钥长度
    private static final int KEY_LENGTH = 256;
    // 算法名称
    private static final String ALGORITHM = "PBKDF2WithHmacSHA256";

    public static String encode(String rawPassword) {
        return encode(rawPassword, null);
    }

    // 加密密码方法
    public static String encode(String rawPassword, Integer iterations) {
        try {
            // 生成随机盐值
            byte[] salt = new byte[16];
            SecureRandom secureRandom = new SecureRandom();
            secureRandom.nextBytes(salt);

            if (iterations == null || iterations <=1) {
                iterations = ITERATIONS;
            }
            // 创建 PBEKeySpec 对象
            PBEKeySpec spec = new PBEKeySpec(rawPassword.toCharArray(), salt, iterations, KEY_LENGTH);
            // 获取 SecretKeyFactory 实例
            SecretKeyFactory skf = SecretKeyFactory.getInstance(ALGORITHM);
            // 生成加密后的密钥
            byte[] hash = skf.generateSecret(spec).getEncoded();

            // 将盐值和加密后的密钥进行 Base64 编码
            return Base64.getEncoder().encodeToString(salt) + ":" + Base64.getEncoder().encodeToString(hash);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
    }

    // 校验密码方法
    public static boolean check(String rawPassword, String encodedPassword) {
        try {
            // 分割存储的加密密码，获取盐值和加密后的密钥
            String[] parts = encodedPassword.split(":");
            byte[] salt = Base64.getDecoder().decode(parts[0]);
            byte[] hash = Base64.getDecoder().decode(parts[1]);

            // 创建 PBEKeySpec 对象
            PBEKeySpec spec = new PBEKeySpec(rawPassword.toCharArray(), salt, ITERATIONS, KEY_LENGTH);
            // 获取 SecretKeyFactory 实例
            SecretKeyFactory skf = SecretKeyFactory.getInstance(ALGORITHM);
            // 生成新的加密后的密钥
            byte[] testHash = skf.generateSecret(spec).getEncoded();

            // 比较两个加密后的密钥是否相等
            return java.util.Arrays.equals(hash, testHash);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
    }
}
